<?php
namespace Plugin;

//模板解析驱动
class template
{
    private $fang; //是否去除注释换行空格配置
    private $view_DIR; //视图目录
    private $path; //模板路径
    private $CACHE_DIR; //模板缓存路径

    private $content; //模板内容
    /**
     * 模板类执行方法
     * @param  String     $path        要解析模板路径
     * @param  String     $CACHE_DIR    模板缓存保存路径
     * @param  String     $fang        是否去除注释换行空格配置
     * @return void
     */
    public static function run($view_DIR, $path, $CACHE_DIR, $fang = false)
    {
        static $obj         = null;
        empty($obj) && $obj = new template();
        $obj->fang          = $fang;
        $obj->path          = $path;
        $obj->view_DIR      = $view_DIR;
        $obj->CACHE_DIR     = $CACHE_DIR;
        $obj->content       = $obj->getContent($path);
        $obj->parsing();
        $obj->setCacheContent();
    }
    /**
     * 读取模板内容
     * @param  String     $path    要解析的内容
     * @return void
     */
    private function getContent($path)
    {
        if (($r = @fopen($path, 'r')) === false) {
            //core::show_error('模版文件没有读取或执行权限，请检查！');
        }
        $content = fread($r, filesize($path));
        fclose($r);
        return $content;
    }
    /**
     * 模板解析
     * @return void
     */
    private function parsing()
    {
        $this->content = $this->parsing_include($this->content); //解析include标签
        $pattern       = [
            "/{(\\$[^}]+)}/", //输出PHP变量
            "/<php:else\s{0,}\/>/", //php ELSE语句解析规则
            "/<php:elseif\s+value\s{0,}=\s{0,}[\"|']([^<]+)[\"|']\s{0,}\/>/", //php ELSEIF语句解析规则
            "/<php:function\s+value\s{0,}=\s{0,}[\"|']([^<]+)[\"|']\s{0,}>/", //php 自定义函数
            "/<\/php:function>/", //php自定义函数结束解析规则
            "/<php:([A-Za-z]+)\s+value\s{0,}=\s{0,}[\"|']([^<]+)[\"|']\s{0,}\/>/", //php语句解析规则
            "/<php:foreach\s+value\s{0,}=\s{0,}[\"|']([^<]+)[\"|']\s{0,}>/", //foreach语句解析规则
            "/<\/php:foreach>/", //foreach结束语句解析规则
            "/<php:([A-Za-z]+)\s+value\s{0,}=\s{0,}[\"|']([^<]+)[\"|']\s{0,}>/", //php语句解析规则
            "/<\/php:([^<]+)>/", //php结束语句解析规则
            "/\seq\s/", //等于         ==
            "/\sneq\s/", //不等于     !=
            "/\sgt\s/", //大于         >
            "/\sgte\s/", //大于等于     >=
            "/\slt\s/", //小于         <
            "/\slte\s/", //小于等于     <=
            "/\sheq\s/", //恒等于     ===
            "/\snheq\s/", //不恒等于     !==
            "/\segt\s/", //等于大于     =>
        ];
        $replacement = [
            "<?php echo $1 ?>",
            "<?php else: ?>",
            "<?php else if($1): ?>",
            "<?php function $1{ ?>",
            "<?php } ?>",
            "<?php $1($2) ?>",
            "<?php \$_i=isset(\$i)?\$i:0;\$i=0;foreach($1):\$i++;?>",
            "<?php endforeach;\$i=\$_i;?>",
            "<?php $1($2): ?>",
            "<?php end$1; ?>",
            " == ",
            " != ",
            " > ",
            " >= ",
            " < ",
            " <= ",
            " === ",
            " !== ",
            " => ",
        ];
        if ($this->fang) {
            $pattern[]     = "/\s{2,}/";
            $pattern[]     = "/\r\n/";
            $pattern[]     = "/<!--[^<]+-->/";
            $replacement[] = " ";
            $replacement[] = "";
            $replacement[] = "";
        }
        $this->content = preg_replace($pattern, $replacement, $this->content);
    }
    /**
     * 模板解析--include
     * @param  String     $content    要解析的内容
     * @return void
     */
    private function parsing_include($content)
    {
        $find = preg_match_all("/<php:include\s+value\s{0,}=\s{0,}[\"|']([^<]+)[\"|']\s{0,}\/>/", $content, $matches);
        if (!$find) {
            return $content;
        }

        for ($i = 0; $i < $find; $i++) {
            $content = str_replace($matches[0][$i], $this->parsing_include_item($matches[1][$i]), $content);
        }
        return $content;
    }
    /**
     * 模板解析--include文件中的include
     * @param  String     $path    要include文件的路径
     * @return void
     */
    private function parsing_include_item($path)
    {
        $content = $this->getContent($this->view_DIR . $path);
        return $this->parsing_include($content);
    }
    /**
     * 设置生成模板缓存
     * @return void
     */
    private function setCacheContent()
    {
        $dir = dirname($this->CACHE_DIR);
        !is_dir($dir) && mkdir($dir);
        if (($w = @fopen($this->CACHE_DIR, 'w')) === false) {
            //core::show_error('模版文件没有读取或执行权限，请检查！');
        }
        fwrite($w, $this->content);
        fclose($w);
    }
}
